package org.jsping.filter;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.annotation.WebInitParam;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;

/*过滤器
 * 主要用来:1.过滤字符集的设置  2.过滤html页面的转义  3.过滤敏感字符,替换成其他文字
 * */
@WebFilter(
		urlPatterns="/*",
		initParams= {
			@WebInitParam(name="path",value="test.txt")
		}
)
public class MyFilter implements Filter{
	private FilterConfig config;  //过滤器
	private String defaultCharset = "utf-8";  //过滤的字符
	
	@Override
	public void destroy() {
	}

	/*重写doFilter来实现过滤*/
	@Override
	public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2)
			throws IOException, ServletException {
		HttpServletRequest request = (HttpServletRequest)arg0;
		HttpServletResponse response = (HttpServletResponse)arg1;
		String charset = config.getInitParameter("encoding");
		if(charset == null) {
			charset = defaultCharset;
		}
		request.setCharacterEncoding(charset);
		response.setCharacterEncoding(charset);
		response.setHeader("Access-Control-Allow-Origin", "*"); 
		response.setContentType("text/html;charset="+charset);
		
		MyRequest req = new MyRequest(request);  //初始化自定义实现的增强类
		arg2.doFilter(req, response);   //让FilterChain执行过滤
	}

	@Override
	public void init(FilterConfig config) throws ServletException {
		this.config = config;
	}
	
	/*自定义实现类增强request*/
	class MyRequest extends HttpServletRequestWrapper{
		private HttpServletRequest request;	
		
		public MyRequest(HttpServletRequest request) {
			super(request);
			this.request = request;
		}

		/*重写getParameter方法*/
		@Override
		public String getParameter(String name) {
			String value = null;
			try {
				value = this.request.getParameter(name); //获取值
				if(value == null) return null;
				//判断请求的方式,如果是get方式,对字符进行处理
				if(this.request.getMethod().equalsIgnoreCase("get")) {
					value = new String(value.getBytes("ISO8859-1"), this.request.getCharacterEncoding());
					value = filter(value);   //进行html转义
				}else {
					value = filter(value);
				}
				
				//进行敏感字符过滤  获取敏感字符的集合
				List<String> minganWords = getWords();
				for(String word:minganWords) {
					if (value.contains(word)) {
						value = value.replace(word, "");
					}
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
			return value;
		}
		
		/*用来对html进行转义的过滤*/
		private String filter(String param) {
			if(param == null) return null;
			char[] contents = new char[param.length()];  //参数的字节数
			param.getChars(0, param.length(), contents, 0);
			StringBuffer sb = new StringBuffer(contents.length+50);  //这里为什么要加50
			for (int i = 0; i < contents.length; i++) {
				//中文不需要转义,只对特殊符号进行转义处理
				switch (contents[i]) {
					case '>':
						sb.append("&gt;");
						break;
					case '<':
						sb.append("&lt;");
						break;
					case '&':
						sb.append("&amp;");
						break;
					case '"':
						sb.append("&quot;");
						break;
					default:
						sb.append(contents[i]);
						break;
				}
			}
			return sb.toString();
		}
		
		/*获取敏感字符串的集合*/
		private List<String> getWords() {
			List<String> words = new ArrayList<String>();
			String path  = config.getInitParameter("path");
			if(path == "" || path == null) return null;
			InputStream is = null;
			InputStreamReader isr = null;
			BufferedReader br = null;
			try {
				is = config.getServletContext().getResourceAsStream(path);  
				//根据路径拿到对应的流,用流去读取对应的数据,也可以利用properties文件来读取
				isr = new InputStreamReader(is);
				br = new BufferedReader(isr);
				String line = "";
				while((line=br.readLine())!=null) {
					words.add(line);
				}
			} catch (Exception e) {
				e.printStackTrace();
			}finally {
				try {
					if (br!=null) {
						br.close();
					}
					if (isr!=null) {
						isr.close();
					}
					if (is!=null) {
						is.close();
					}
				} catch (Exception e2) {
					e2.printStackTrace();
				}
			}
			return words;
		}
	}
}
